import { useRef, useEffect, useState } from 'react';
import { obj_str, loc, for_obj, is_empty, uDb, cline, d_sort } from 'sui';

const g_reload = (hDone, url, ucmd, ignore, setValue, sort="sn") => {
    if (!url) {
        return;
    }

    const cmd = {"line": cline()};
    for_obj(ucmd, (k, v) => cmd[k] = v);

    uDb(hDone, url, cmd,
        data => {
            if (is_empty(data)) {
                setValue(null);
                return;
            }

            if (ignore) {
                const set = new Set();
                ignore.forEach(d => set.add(d));

                data = data.filter(d => !set.has(d.sn));
            }

            d_sort(data, sort);
            data.forEach((d, i) => d["index"] = i + 1);

            setValue(data);
        },
        e => setValue(null));
};

const useCmd = (url, ignore=null, ucmd=null, sort="sn") => {
    const [value, setValue] = useState();
    const [filter, setFilter] = useState("");
    const [cur, setCur] = useState();
    const [fin, setFin] = useState();
    const [wait, setWait] = useState(false);
    const [info, setInfo] = useState(null);
    const [wrong, setWrong] = useState(null);
    const [pos, setPos] = useState(null);
    const gref = useRef();

    useEffect(() => {
        if (!url) {
            return;
        }

        g_reload(null, url, ucmd, ignore, setValue, sort);
    }, [url, setValue]);

    const hreturn = () => {
        setFin(null);

        const curpos = pos;
        setPos(0);

        if (curpos < 20) {
            return;
        }

        let num = 0;

        const id = setInterval(() => {
            num += 1;
            if (num > 10) {
                clearInterval(id);
                return;
            }

            if (!gref.current) {
                return;
            }

            gref.current.scrollToRow(curpos - 1);
            clearInterval(id);
        }, 300);
    };

    const isFin = (v) => {
        return v === fin;
    };

    const startWait = () => {
        setWrong(null);
        setInfo(null);
        setWait(true);
    };

    const endWait = (info=null) => {
        setWrong(null);
        setInfo(info);
        setWait(false);
    };

    const setErr = (v=loc("l_232")) => {
        setWrong(v);
        setInfo(null);
        setWait(false);
    };

    const do_action = (cmd, val, hcmd, ext) => {
        if (!cmd) {
            return;
        }

        if (ext) {
            const h = cmd[obj_str(fin, ext)];
            if (h) {
                h(val, hcmd);
            }

            return;
        }

        const h = cmd[fin];
        if (h) {
            h(val, hcmd);
        }
    };

    const pre_action = (cmd, val, tp, ext) => {
        if (ext) {
            setFin(ext);
        } else {
            setFin(tp);
        }

        setCur(val);

        if (val && val.posid) {
            setPos(val.posid);
        }

        if (!cmd) {
            return;
        }

        const h = cmd[tp];
        if (h) {
            h(val);
        }
    };

    const update = (up_url, cmd, hcmd) => {
        startWait();

        uDb(null, up_url,
            {
                "line": cline(),
                ...cmd,
            },
            r => {
                g_reload(endWait, url, ucmd, ignore, setValue, sort);
                if (hcmd) {
                    hcmd();
                }
            },
            e => setErr(loc("l_232")), true);
    };

    const reload = (hDone) => g_reload(hDone, url, ucmd, ignore, setValue, sort);

    return {
        // value
        value: value,
        cur: cur,
        fin: fin,
        filter: filter,
        wait: wait,
        info: info,
        wrong: wrong,

        // function: set value
        setValue: setValue,
        setCur: setCur,
        setFin: setFin,
        setFilter: setFilter,

        hreturn: hreturn, // return from sub view
        isFin: isFin,     // judge fin's value

        // function: wait
        startWait: startWait,
        endWait: endWait,
        setErr: setErr,

        // function: load and update
        reload: reload,
        update: update, // add or modify data

        // function: for button click action
        act: do_action,   // return from dlg
        pact: pre_action, // open dlg

        gref: gref,
        setPos: setPos,
    };
};

export {useCmd};
